package com.dfiles.provider;

import java.io.File;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.TransitionDrawable;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.provider.MediaStore.Video.Thumbnails;
import android.util.Log;
import android.util.LruCache;
import android.widget.ImageView;

import com.dfiles.Config;
import com.dfiles.provider.FileTypeHelper.FileTypeAll;
import com.dfiles.utils.FileUtils;

/**
 * 图片加载类
 * 
 */
public class ImageManager {

	private static final int DISK_CACHE_SIZE = 1024 * 1024 * 20; // 10MB
	private static final String DISK_CACHE_SUBDIR = "thumbnails";

	private Context context;
	private static ImageManager imageManager;
	public LruCache<String, Bitmap> mMemoryCache;
	public DiskLruCache mDiskCache;

	/** 图片加载队列，后进先出 */
	private Stack<ImageRef> mImageQueue = new Stack<ImageRef>();
	/** 图片请求队列，先进先出，用于存放已发送的请求。 */
	private Queue<ImageRef> mRequestQueue = new LinkedList<ImageRef>();

	/** 图片加载线程消息处理器 */
	private Handler mImageLoaderHandler;
	/** 图片加载线程是否就绪 */
	private boolean mImageLoaderIdle = true;
	/** 请求图片 */
	private static final int MSG_REQUEST = 1;
	/** 图片加载完成 */
	private static final int MSG_REPLY = 2;
	/** 中止图片加载线程 */
	private static final int MSG_STOP = 3;

	public static ImageManager from(Context context) {
		// 如果不在ui线程中，则抛出异常
		if (Looper.myLooper() != Looper.getMainLooper()) {
			throw new RuntimeException("Cannot instantiate outside UI thread.");
		}
		if (imageManager == null) {
			imageManager = new ImageManager(context);
		}
		return imageManager;
	}

	/**
	 * 构造器
	 * 
	 * @param context
	 */
	public ImageManager(Context context) {
		this.context = context;
		int memClass = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();
		memClass = memClass > 32 ? 32 : memClass;
		final int cacheSize = 1024 * 1024 * memClass / 8;
		mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
			// protected int sizeOf(String key, Bitmap bitmap) {
			// return bitmap.getRowBytes() * bitmap.getHeight();
			// }
		};
		File cacheDir = DiskLruCache.getDiskCacheDir(context, DISK_CACHE_SUBDIR);
		mDiskCache = DiskLruCache.openCache(context, cacheDir, DISK_CACHE_SIZE);
	}

	/**
	 * 显示图片固定大小图片的缩略图，一般用于显示列表的图片，可以大大减小内存使用
	 * 
	 * @param imageView
	 *            加载图片的控件
	 * @param url
	 *            加载地址
	 * @param resId
	 *            默认图片
	 * @param width
	 *            指定宽度
	 * @param height
	 *            指定高度
	 */
	public void displayImage(ImageView imageView, FileTypeAll fileType, String url, int resId, int width, int height) {
		if (imageView == null) {
			return;
		}
		if (resId >= 0) {
			if (imageView.getBackground() == null) {
				imageView.setBackgroundResource(resId);
			}
			imageView.setImageDrawable(null);
		}
		if (url == null || url.equals("")) {
			return;
		}
		// 添加url tag
		imageView.setTag(url);
		// 读取map缓存
		Bitmap bitmap = mMemoryCache.get(url + width + height);
		if (bitmap != null) {
			setImageBitmap(imageView, bitmap, false);
			return;
		}
		// 生成缓存文件名
		String filePath = urlToFilePath(url);
		if (filePath == null) {
			return;
		}
		queueImage(new ImageRef(imageView, fileType, url, filePath, resId, width, height));
	}

	/**
	 * 入队，后进先出
	 * 
	 * @param imageRef
	 */
	public void queueImage(ImageRef imageRef) {
		// 删除已有ImageView
		Iterator<ImageRef> iterator = mImageQueue.iterator();
		while (iterator.hasNext()) {
			if (iterator.next().imageView == imageRef.imageView) {
				iterator.remove();
			}
		}

		// 添加请求
		mImageQueue.push(imageRef);
		sendRequest();
	}

	/**
	 * 发送请求
	 */
	private void sendRequest() {

		// 开启图片加载线程
		if (mImageLoaderHandler == null) {
			HandlerThread imageLoader = new HandlerThread("image_loader");
			imageLoader.start();
			mImageLoaderHandler = new ImageLoaderHandler(imageLoader.getLooper());
		}

		// 发送请求
		if (mImageLoaderIdle && mImageQueue.size() > 0) {
			ImageRef imageRef = mImageQueue.pop();
			Message message = mImageLoaderHandler.obtainMessage(MSG_REQUEST, imageRef);
			mImageLoaderHandler.sendMessage(message);
			mImageLoaderIdle = false;
			mRequestQueue.add(imageRef);
		}
	}

	/**
	 * 图片加载线程
	 */
	class ImageLoaderHandler extends Handler {

		public ImageLoaderHandler(Looper looper) {
			super(looper);
		}

		public void handleMessage(Message msg) {
			if (msg == null)
				return;
			switch (msg.what) {
				case MSG_REQUEST : // 收到请求
					Bitmap bitmap = null;
					if (msg.obj != null && msg.obj instanceof ImageRef) {
						ImageRef imageRef = (ImageRef) msg.obj;
						String url = imageRef.url;
						// Log.d(ImageManager.class.getName() + "---请求URL=",
						// url);
						FileTypeAll fileType = imageRef.fileType;
						if (url == null) {
							return;
						}
						bitmap = mDiskCache.get(url + imageRef.width + imageRef.height);
						/* 加入硬盘缓存中存在 */
						if (bitmap != null) {
							Log.d(ImageManager.class.getName(), "从disk缓存读取");
							// 写入map缓存
							if (imageRef.width != 0 && imageRef.height != 0) {
								if (mMemoryCache.get(url + imageRef.width + imageRef.height) == null)
									mMemoryCache.put(url + imageRef.width + imageRef.height, bitmap);
							}
							// else {
							// if (mMemoryCache.get(url) == null)
							// mMemoryCache.put(url, bitmap);
							// }
						} else {// 缓存中不存在
							try {
								if (fileType == FileTypeAll.FILE_TYPE_IMAGE) {
									bitmap = FileUtils.getImageThumbnail(url, Config.UI.THUMBNAIL_WIDTH_SQUARE, Config.UI.THUMBNAIL_WIDTH_SQUARE);
								}
								if (fileType == FileTypeAll.FILE_TYPE_VIDEO) {
									bitmap = FileUtils.getVideoThumbnail(url, Config.UI.THUMBNAIL_WIDTH_RECT, Config.UI.THUMBNAIL_HEIGHT_RECT, Thumbnails.MINI_KIND);
								}

								if (bitmap != null && url != null) {
									// 写入SD卡
									if (imageRef.width != 0 && imageRef.height != 0) {
										mDiskCache.put(url + imageRef.width + imageRef.height, bitmap);
										mMemoryCache.put(url + imageRef.width + imageRef.height, bitmap);
									} else {
										mDiskCache.put(url, bitmap);
										mMemoryCache.put(url, bitmap);
									}
								}
							} catch (OutOfMemoryError e) {
								e.printStackTrace();
							}
						}
					}
					if (mImageManagerHandler != null) {
						Message message = mImageManagerHandler.obtainMessage(MSG_REPLY, bitmap);
						mImageManagerHandler.sendMessage(message);
					}
					break;
				case MSG_STOP : // 收到终止指令
					Looper.myLooper().quit();
					break;

			}
		}
	}

	/** UI线程消息处理器 */
	private Handler mImageManagerHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			if (msg != null) {
				switch (msg.what) {
					case MSG_REPLY : // 收到应答

						do {
							ImageRef imageRef = mRequestQueue.remove();
							if (imageRef == null)
								break;
							if (imageRef.imageView == null || imageRef.imageView.getTag() == null || imageRef.url == null)
								break;

							if (!(msg.obj instanceof Bitmap) || msg.obj == null) {
								break;
							}
							Bitmap bitmap = (Bitmap) msg.obj;
							// 非同一ImageView
							if (!(imageRef.url).equals((String) imageRef.imageView.getTag())) {
								break;
							}
							setImageBitmap(imageRef.imageView, bitmap, true);
						} while (false);

						break;
				}
			}
			// 设置闲置标志
			mImageLoaderIdle = true;
			// 若服务未关闭，则发送下一个请求。
			if (mImageLoaderHandler != null) {
				sendRequest();
			}
		}
	};

	/**
	 * 添加图片显示渐现动画
	 * 
	 */
	private void setImageBitmap(ImageView imageView, Bitmap bitmap, boolean isTran) {
		if (isTran) {
			final TransitionDrawable td = new TransitionDrawable(new Drawable[]{new ColorDrawable(android.R.color.transparent), new BitmapDrawable(bitmap)});
			td.setCrossFadeEnabled(true);
			imageView.setImageDrawable(td);
			td.startTransition(300);
		} else {
			imageView.setImageBitmap(bitmap);
		}
	}

	/**
	 * 根据url生成缓存文件完整路径名
	 * 
	 * @param url
	 * @return
	 */
	private String urlToFilePath(String url) {
		// 扩展名位置
		int index = url.lastIndexOf('.');
		if (index == -1) {
			return null;
		}
		StringBuilder filePath = new StringBuilder();
		File file = context.getCacheDir();
		// 图片存取路径
		filePath.append(file.toString()).append('/');
		// 图片文件名
		filePath.append(MD5.Md5(url)).append(url.substring(index));
		return filePath.toString();
	}

	/**
	 * 存放图片信息
	 */
	class ImageRef {
		/** 图片对应ImageView控件 */
		ImageView imageView;
		/* 文件类型-默认为图片，也可能是video生成的缩略图 */
		FileTypeAll fileType = FileTypeAll.FILE_TYPE_IMAGE;
		/** 图片URL地址 */
		String url;
		/** 图片缓存路径 */
		String filePath;
		/** 默认图ID */
		int resId;
		int width = 0;
		int height = 0;

		/**
		 * 构造函数
		 * 
		 * @param imageView
		 * @param url
		 * @param resId
		 * @param filePath
		 */
		ImageRef(ImageView imageView, String url, String filePath, int resId) {
			this.imageView = imageView;
			this.url = url;
			this.filePath = filePath;
			this.resId = resId;
		}

		ImageRef(ImageView imageView, String url, String filePath, int resId, int width, int height) {
			this.imageView = imageView;
			this.url = url;
			this.filePath = filePath;
			this.resId = resId;
			this.width = width;
			this.height = height;
		}

		ImageRef(ImageView imageView, FileTypeAll fileType, String url, String filePath, int resId, int width, int height) {
			this.fileType = fileType;
			this.imageView = imageView;
			this.url = url;
			this.filePath = filePath;
			this.resId = resId;
			this.width = width;
			this.height = height;
		}

	}
}
